-- Decompiled with the Synapse X Luau decompiler.

local InsertService = game:GetService("InsertService");
local RunService = game:GetService("RunService");
local M = {};
local nowTime = os.time();

function M.Random(self, r1, r2)
	nowTime = nowTime + 1;
	math.randomseed(nowTime);
	if r1 and r2 then
		return math.random(r1, r2);
	end;
	return math.random();
end;
local FindTime = 10;

local function FindChilld(name, parent, time)
	time = time or FindTime;
	return parent:WaitForChild(name, time);
end;


function M.GetPath(self, path, Object, time)
	assert(path, "param path string is nil");
	local tpy = typeof(path);
	assert(tpy == "string", "param path string must be a string,not " .. tpy);
	Object = Object or game;
	local tpy2 = typeof(Object);
	assert(Object and tpy2 == "Instance", "param base must be a instance,not " .. tpy2);
	local name = Object.Name;

	for childName in string.gmatch(path, "[%a%d_]+") do
		local obj = FindChilld(childName, Object, time);
		if not obj then
			warn("get inst with path = " .. path .. " form " .. Object.Name .. " time out!\nStopped at " .. name .. "\n" .. debug.traceback(coroutine.running()));
			return;
		end;
		Object=obj
		name = name .. "." .. childName;
	end;
	return Object;
end;
function M.GetPath_Check(self, path, Object, time)
	local obj = self:GetPath(path, Object, time);
	assert(obj, "get inst with path " .. path .. " time out!");
	return obj;
end;
function M.GetPath_Loop(self, path, object, time)
	local obj = self:GetPath(path, object, time);
	while not obj do
		obj = self:GetPath(path, object, time);	
	end;
	return obj;
end;

local function StringPath(p)
	if type(p) == "string" then
		p = "\"" .. p .. "\"";
	end;
	if type(p) == "number" and p > 4294967295 then
		return string.format("0x%x", p);
	end;
	return tostring(p);
end;


local function Table2String(arg1, arg2, arg3)
	assert(arg1, "param value is nil");
	if type(arg3) ~= "number" then
		arg3 = 5;
	end;
	local data = {};
	local tempData = {};
	local function fulldata(p23, p24, p25, p26, p27)
		--p24 = p24 and "<var>";
		p24 = p24 or "<var>";
		local v10 = "";
		if type(p27) == "number" then
			v10 = string.rep(" ", p27 - string.len(StringPath(p24)));
		end;
		if type(p23) ~= "table" then
			data[#data + 1] = string.format("%s%s%s = %s", p25, StringPath(p24), v10, StringPath(p23));
			return;
		end;
		if tempData[tostring(p23)] then
			data[#data + 1] = string.format("%s%s%s = *REF*", p25, StringPath(p24), v10);
			return;
		end;
		tempData[tostring(p23)] = true;
		if arg3 < p26 then
			data[#data + 1] = string.format("%s%s = *MAX NESTING*", p25, StringPath(p24));
			return;
		end;
		data[#data + 1] = string.format("%s%s = {", p25, StringPath(p24));
		local v11 = p25 .. "    ";
		local v12 = {};
		local v13 = 0;
		local v14 = {};
		for v15, v16 in pairs(p23) do
			v12[#v12 + 1] = v15;
			local v17 = string.len((StringPath(v15)));
			if v13 < v17 then
				v13 = v17;
			end;
			v14[v15] = v16;
		end;
		table.sort(v12, function(p28, p29)
			if type(p28) == "number" and type(p29) == "number" then
				return p28 < p29;
			end;
			return tostring(p28) < tostring(p29);
		end);
		for v18, v19 in ipairs(v12) do
			fulldata(v14[v19], v19, v11, p26 + 1, v13);
		end;
		data[#data + 1] = string.format("%s}", p25);
	end;
	fulldata(arg1, arg2, "", 1);
	print(table.concat(data, "\n"));
end;
function M.PrintTable(self, data, p32, p33)
	Table2String(data, p32, p33);
end;

function M.Dump(p34, p35, p36, p37)
	if not next(p35) then
		return "{ }";
	end;
	local u25 = {};
	local u26 = p37 and 5;
	local function u27(p38, p39)
		local v20 = "\n" .. string.rep("\t", p39) .. "{\n";
		local v21, v22, v23 = pairs(p38);
		while true do
			local v24, v25 = v21(v22, v23);
			if not v24 then
				break;
			end;
			local v26 = 1
			if type(v24) == "string" then
				v26 = 1;
			else
				v26 = 0;
			end;
			local v27 = 1;
			if type(v25) == "string" then
				v27 = 1;
			else
				v27 = 0;
			end;
			local v28 = v20 .. string.rep("\t", p39 + 1) .. "[" .. string.rep("\"", v26) .. (tostring(v24) or type(v24)) .. string.rep("\"", v26) .. "] = ";
			if type(v25) == "table" then
				if not u25[v25] and (not u26 or p39 < u26) then
					u25[v25] = true;
					if next(v25) then
						v20 = v28 .. u27(v25, p39 + 1, p36) .. "\n";
					else
						v20 = v28 .. "{ }\n";
					end;
				elseif next(v25) then
					v20 = v28 .. (tostring(v25) or type(v25)) .. ",\n";
				else
					v20 = v28 .. "{ },\n";
				end;
			else
				v20 = v28 .. string.rep("\"", v27) .. (tostring(v25) or type(v25)) .. string.rep("\"", v27) .. ",\n";
			end;		
		end;
		if p36 then
			local v29 = getmetatable(p38);
			if v29 ~= nil and type(v29) == "table" then
				local M0 = v20 .. string.rep("\t", p39 + 1) .. "[\"__metatable\"] = ";
				if not u25[v29] and (not u26 or p39 < u26) then
					u25[v29] = true;
					v20 = M0 .. u27(v29, p39 + 1, p36) .. "\n";
				else
					--v20 = M0 .. (tostring(v) or type(v)) .. ",\n";
					v20 = M0  .. "程序错误!,\n";
				end;
			end;
		end;
		return v20 .. string.rep("\t", p39) .. "},";
	end;
	return u27(p35, 0);
end;
function M.DeepCopy(self, source,dest)
	assert(source, "param tab is nil");
	assert(typeof(source) == "table", "param tab must be a table");
	local data = dest or {};
	for k, v in pairs(source) do
		if type(v) ~= "table" then
			data[k] = v;
		else
			data[k] = self:DeepCopy(v);
		end;
	end;
	return data;
end;
function M.DeepCompare(self,t1,t2)
	if type(t1) ~= "table" or type(t2) ~= "table" then
		return t1==t2
	end

	for k,v in pairs(t1) do
		if not self:DeepCompare(t2[k],v) then
			return false
		end
	end
	for k,v in pairs(t2) do
		if not self:DeepCompare(t1[k],v) then
			return false
		end
	end

	return true
end

function M.CountTable(self, source)
	assert(source, "param tab is nil");
	assert(typeof(source) == "table", "param tab must be a table");
	local count = 0;
	for k, v in pairs(source) do
		count = count + 1;
	end;
	return count;
end;
function M.GetTableKeys(self, source)
	assert(source, "param tab is nil");
	assert(typeof(source) == "table", "param tab must be a table");
	local data = {};
	for k, v in pairs(source) do
		data[#data + 1] = k;
	end;
	return data;
end;
function M.GetTableValues(self, source)
	assert(source, "param tab is nil");
	assert(typeof(source) == "table", "param tab must be a table");
	local data = {};
	for k, v in pairs(source) do
		data[#data + 1] = v;
	end;
	return data;
end;

function M.CloneInst(self, obj, time)
	assert(obj, "param inst is nil");
	local typ = typeof(obj);
	assert(typ == "Instance", "param inst must be instance,now is " .. typ);
	time = time or FindTime;
	if obj:IsA("Model") then
		assert(obj.PrimaryPart, "model " .. obj.Name .. " don't have primary part,plese check");
		assert(obj.PrimaryPart.Archivable, "model " .. obj.Name .. "'s primary part archivable is false, can't clone");
	end;
	local childCount = #obj:GetDescendants();
	for i, o in ipairs(obj:GetDescendants()) do
		if o:IsA("TouchTransmitter") then
			o:Destroy();
			childCount = childCount - 1;
		elseif not o.Archivable then
			childCount = childCount - 1;
		end;
	end;
	local sumWaitTime = 0;
	local cloneObj = obj:Clone();
	while #cloneObj:GetDescendants() < childCount do
		sumWaitTime = sumWaitTime + wait();
		if time <= sumWaitTime then
			warn("clone " .. obj.Name .. " faild,time out");
			return;
		end;	
	end;
	if cloneObj:IsA("Model") then
		while not cloneObj.PrimaryPart do
			sumWaitTime = sumWaitTime + wait();
			if time < sumWaitTime then
				warn("clone " .. obj.Name .. " faild,time out");
				return;
			end;		
		end;
		return cloneObj;
	else
		return cloneObj;
	end;

end;
function M.CloneInst_Check(self, obj, time)
	local cloneObj = self:CloneInst(obj, time);
	assert(cloneObj, "clone inst " .. obj.Name .. " time out");
	return cloneObj;
end;
function M.CloneInst_Loop(self, obj, time)
	local cloneObj = self:CloneInst(obj, time);
	while not cloneObj do
		cloneObj = self:CloneInst(obj, time);	
	end;
	return cloneObj;
end;
function M.SetDefaultTimeLimit(self, limitTime)
	assert(limitTime, "param time limit is nil");
	assert(typeof(limitTime) == "number", "param time limit must be number");
	FindTime = limitTime;
end;
function M.GetDefaultTimeLimit(self)
	return FindTime;
end;

function M.mIsLoading(self,data)
	local isDone=false
	for _, v in pairs(data:GetChildren()) do
		if v:isA("ModuleScript") then
			local t=require(v)
			if t.isDone then
				isDone=t.isDone()
			end
		end
	end
	return isDone
end


function M.InitFiles(self, fileList)
	self.__file_list = fileList;
	local data = {};
	for k, v in pairs(fileList) do
		data[k] = function(path)
			local obj = self:GetPath_Loop(v, game, path);
			data[k] = function()
				return obj;
			end;
			return obj;
		end;
	end;
	return data;
end;

function M.AsyncLoadAsset(self, assetId,waitFuc)
	local asset=nil
	local a,b=pcall(function()
		asset=InsertService:LoadAsset(assetId)
		asset.Parent=script
	end)
	if not a then
		return
	end
	if self:mIsLoading(asset) then
		return asset
	elseif waitFuc then
		waitFuc(asset)
	end
end


function M.InitLoads(self, list) --初始化脚本
	local data = {};
	for k, v in pairs(list) do
		data[k] = function(arg)
			local info = nil;
			local s = nil;
			s, info = xpcall(require, debug.traceback, self.files[k](arg));
			if not s then
				warn(info);
				return;
			end;
			data[k] = function()
				return info;
			end;
			return info;
		end;
	end;
	return data;
end;
function M.InitResource(self, resource)
	local rdata = {};
	for k, v in pairs(resource) do
		if type(v) == "table" then
			rdata[k] = self:InitResource(v);
		else
			rdata[k] = function(path)
				local obj = self:GetPath_Loop(v, game, path);
				rdata[k] = function(inst)
					return self:CloneInst_Loop(obj, inst);
				end;
				return self:CloneInst_Loop(obj, path);
			end;
		end;
	end;
	return rdata;
end;
function M.InitConfig(self)
	local d = nil;
	local s = nil;
	s, d = xpcall(require, debug.traceback, (self:GetPath_Check("ReplicatedStorage.Config", game)));
	if s then
		return d;
	end;
	warn(d);
end;


function M.Preload(self, p72, p73, p74)
	local v78 = coroutine.running();
	local v79 = 0;
	local v80 = 0;
	local v81 = {};
	for v82, v83 in pairs(self.__file_list) do
		v79 = v79 + 1;
		v80 = v80 + 1;
		local FindTime5 = v80;
		v81[v82] = coroutine.wrap(function()
			local v84 = nil;
			local v85 = nil;
			v85, v84 = pcall(function()
				self.files[v82](p74, not p73);
				FindTime5 = FindTime5 - 1;
				if p72 then
					p72(v79, v79 - FindTime5, v82, v83);
				end;
				if FindTime5 <= 0 then
					wait();
					coroutine.resume(v78);
				end;
			end);
			if not v85 then
				if not p73 then
					error(v84);
					return;
				end;
			else
				return;
			end;
			p73(v84, v82, v83);
		end);
	end;
	for v86, v87 in pairs(v81) do
		v87();
	end;
	coroutine.yield();
end;


return M;
